#pragma once

#include"log.hpp"
#include"Lock.hpp"
#include"Task.hpp"

#include<iostream>
#include<queue>
#include<cassert>
#include<unistd.h>
#include<pthread.h>


using namespace std;

template<class T>
class threadpool
{
public:
    static threadpool<T>* getinstance()
    {
        static Mutex mutex;
        if (nullptr == instance)
        {
            LockGuard Lockguard(&mutex);
            if (instance == nullptr)
            {
                instance = new threadpool<T>();
            }
        }
        return instance;
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

    static void* ThreadRoutine(void* argc)
    {
        pthread_detach(pthread_self());
        threadpool<T>* p=static_cast<threadpool<T>*>(argc);
        while(true)
        {
            p->mutex_lock_();
            while(!p->haveTask())
            {  
                p->cond_wait_();//使用条件变量，阻塞住线程，让线程排队
            }
            T tmp=p->pop();
            p->mutex_unlock_();
            //执行任务
            tmp();
        }
    }
    void start()
    {
        assert(!isStart_);
        for(int i=0;i<threadnum_;i++)
        {
            pthread_t tid;
            pthread_create(&tid,nullptr,ThreadRoutine,this);

        }
        isStart_=true;
    }
    void push(const T& in)
    {
        mutex_lock_();
        dq_.push(in);
        cond_signal_();
        mutex_unlock_();
    }
    int thread_num()
    {
        return threadnum_;
    }
private:
    threadpool(int threadnum=5):threadnum_(threadnum),isStart_(false)
    {
        pthread_mutex_init(&mutex_,nullptr);
        pthread_cond_init(&cond_,nullptr);
    }
    threadpool(const threadpool<T> &) = delete;
    void operator=(const threadpool<T> &) = delete;

    T pop()
    {
        T tmp = dq_.front();
        dq_.pop();
        return tmp;
    }
    bool haveTask() 
    { 
        return !dq_.empty(); 
    }
    void mutex_lock_()
    {
        pthread_mutex_lock(&mutex_);
    }
    void mutex_unlock_()
    {
        pthread_mutex_unlock(&mutex_);
    }
    void cond_wait_()
    {
        pthread_cond_wait(&cond_,&mutex_);
    }
    void cond_signal_()
    {
        pthread_cond_signal(&cond_);
    }
private:
    bool isStart_;          //是否开始
    int threadnum_;         //线程数量
    queue<T>dq_;            //任务队列
    pthread_mutex_t mutex_; //互斥锁
    pthread_cond_t cond_;   //条件变量
    static threadpool<T>* instance; //单例
};

//懒汉模式
template <class T>
threadpool<T> *threadpool<T>::instance = nullptr;
